using System;
using System.Collections;
using System.Text.RegularExpressions;
using SecuBat.AttackPlugin;

namespace SecuBat.Analysis.Common
{
	/// <summary>
	/// Summary description for SimpleKeywordAnalysis.
	/// </summary>
	public class SimpleKeywordAnalysis : AnalysisBase, IAnalysis
	{
		private WeightedKeywordCollection _keywords;
		private int _differentPositiveKeywordsFound;
		private int _absolutePositiveKeywordsFound;
		private int _differentNegativeKeywordsFound;
		private int _absoluteNegativeKeywordsFound;
		private Hashtable _foundKeywordCounts;

		public WeightedKeywordCollection Keywords
		{
			get { return _keywords; }
			set { _keywords = value; }
		}

		public int DifferentPositiveKeywordsFound
		{
			get { return _differentPositiveKeywordsFound; }
			set { _differentPositiveKeywordsFound = value; }
		}

		public int AbsolutePositiveKeywordsFound
		{
			get { return _absolutePositiveKeywordsFound; }
			set { _absolutePositiveKeywordsFound = value; }
		}

		public int DifferentNegativeKeywordsFound
		{
			get { return _differentNegativeKeywordsFound; }
			set { _differentNegativeKeywordsFound = value; }
		}

		public int AbsoluteNegativeKeywordsFound
		{
			get { return _absoluteNegativeKeywordsFound; }
			set { _absoluteNegativeKeywordsFound = value; }
		}

		public Hashtable FoundKeywordsCounts
		{
			get { return _foundKeywordCounts; }
			set { _foundKeywordCounts = value; }
		}

		public SimpleKeywordAnalysis(ICommonData data, WeightedKeywordCollection keywords) : base(data)
		{
			Keywords = keywords;
			DifferentPositiveKeywordsFound = 0;
			AbsolutePositiveKeywordsFound = 0;
			DifferentNegativeKeywordsFound = 0;
			AbsoluteNegativeKeywordsFound = 0;
			FoundKeywordsCounts = new Hashtable();
		}

		public override void DoAnalysis()
		{
			base.DoAnalysis();

			if (this.ResponseHtml != null)
			{
				if (this.ResponseHtml.Length > 0)
				{
          Regex keywordRegex = this.Keywords.KeywordRegex;
					MatchCollection col = keywordRegex.Matches(this.ResponseHtml);
					foreach (Match m in col)
					{
						WeightedKeyword keyword = this.Keywords[m.Value] as WeightedKeyword;
						if (keyword != null)
						{

							if (FoundKeywordsCounts.Contains(keyword.Keyword))
							{
								// Next times, only add a part of the confidence factor
								int timesFound = (int)FoundKeywordsCounts[keyword.Keyword] + 1;
								
								// If more than 25 occurencies of one keyword is found, start to subtract result value again.
								if (timesFound <= 25)
									this.AnalysisResult += keyword.ConfidenceFactor / (timesFound * timesFound);
								else
									this.AnalysisResult -= keyword.ConfidenceFactor / ((timesFound - 25) * (timesFound - 25));

								FoundKeywordsCounts[keyword.Keyword] = timesFound;
								
								if (keyword.ConfidenceFactor >= 0)
									AbsolutePositiveKeywordsFound ++;
								else
									AbsoluteNegativeKeywordsFound ++;
							}
							else
							{
								// First time, add full confidence factor
								this.AnalysisResult += keyword.ConfidenceFactor;
								FoundKeywordsCounts.Add(keyword.Keyword, 1);
								
								if (keyword.ConfidenceFactor >= 0)
								{
									AbsolutePositiveKeywordsFound ++;
									DifferentPositiveKeywordsFound ++;
								}
								else
								{
									AbsoluteNegativeKeywordsFound ++;
									DifferentNegativeKeywordsFound ++;
								}
							}
						}
					}
				}
			}

			// More different positive keywords found => better
			this.AnalysisResult *= DifferentPositiveKeywordsFound;

			AnalysisText = 
				String.Format("Absolute positive keywords: {0}" + Environment.NewLine + 
					"Different positive keywords: {1}" + Environment.NewLine + 
					"Absolute negative keywords: {2}" + Environment.NewLine + "Different negative keywords: {3}",
				this.AbsolutePositiveKeywordsFound, this.DifferentPositiveKeywordsFound, 
				this.AbsoluteNegativeKeywordsFound, this.DifferentNegativeKeywordsFound);

			AnalysisText += Environment.NewLine + Environment.NewLine + "Found keywords: ";
			foreach (String kw in this.FoundKeywordsCounts.Keys)
			{
				AnalysisText += Environment.NewLine + kw + " (" + (int)this.FoundKeywordsCounts[kw] + " times)" + "; ";
			}

		}
	}
}
